#ifndef LINE_STREAM_ITERATOR_H
#define LINE_STREAM_ITERATOR_H


#include <string>
#include <iostream>
#include <iterator>

using namespace std;

template<typename _Tp = std::string, typename _CharT = char, 
	typename _Traits = char_traits<_CharT>, typename _Dist = ptrdiff_t> 
	class line_stream_iterator 
	: public iterator<input_iterator_tag, _Tp, _Dist, const _Tp*, const _Tp&>
{
	public:
		typedef _CharT                         char_type;
		typedef _Traits                        traits_type;
		typedef basic_istream<_CharT, _Traits> istream_type;

	private:
		istream_type*	_M_stream;
		_Tp			_M_value;
		bool		_M_ok;

	public:      
		line_stream_iterator() : _M_stream(0), _M_ok(false) {}

		line_stream_iterator(istream_type& __s) : _M_stream(&__s) { _M_read(); }

		line_stream_iterator(const line_stream_iterator& __obj) 
			: _M_stream(__obj._M_stream), _M_value(__obj._M_value), 
			_M_ok(__obj._M_ok) 
	{ }

		const _Tp& operator*() const { return _M_value; }

		const _Tp* operator->() const { return &(operator*()); }

		line_stream_iterator& operator++() 
		{ _M_read(); return *this; }

		line_stream_iterator operator++(int)  
		{
			line_stream_iterator __tmp = *this;
			_M_read();
			return __tmp;
		}

		bool _M_equal(const line_stream_iterator& __x) const
		{ return (_M_ok == __x._M_ok) && (!_M_ok || _M_stream == __x._M_stream);}

	private:      
		void _M_read() 
		{
			_M_ok = (_M_stream && *_M_stream) ? true : false;
			if (_M_ok) 
			{
				// *_M_stream >> _M_value;
				getline(*_M_stream, _M_value);
				_M_ok = *_M_stream ? true : false;
			}
		}
};

template<typename _Tp, typename _CharT, typename _Traits, typename _Dist>
	inline bool 
operator==(const line_stream_iterator<_Tp, _CharT, _Traits, _Dist>& __x,
		const line_stream_iterator<_Tp, _CharT, _Traits, _Dist>& __y) 
{ return __x._M_equal(__y); }

template <class _Tp, class _CharT, class _Traits, class _Dist>
	inline bool 
operator!=(const line_stream_iterator<_Tp, _CharT, _Traits, _Dist>& __x,
		const line_stream_iterator<_Tp, _CharT, _Traits, _Dist>& __y) 
{ return !__x._M_equal(__y); }


#endif
